﻿#include <iostream>
#include <string>
#include <vector>
#include <regex>
#include <unordered_map>
#include <windows.h>
#include <shlwapi.h>
#pragma comment(lib, "shlwapi.lib")

// 替换字符串中的所有旧字符为新字符
std::string ReplaceAll(const std::string& str, const std::string& oldStr, const std::string& newStr) {
    std::string result = str;
    size_t pos = 0;
    while ((pos = result.find(oldStr, pos)) != std::string::npos) {
        result.replace(pos, oldStr.length(), newStr);
        pos += newStr.length();
    }
    return result;
}

// 获取相对路径
std::string GetRelativePath(const std::string& fullPath, const std::string& basePath) {
    if (fullPath.length() <= basePath.length()) return "";
    return fullPath.substr(basePath.length());
}

// 检查文件是否为.pack后缀且需要重命名
bool NeedsRename(const std::string& filename) {
    // 检查是否为.pack后缀
    if (!PathMatchSpecA(filename.c_str(), "*.pack")) {
        return false;
    }
    else
    {
        return true;
    }

    //// 检查是否已按规则命名
    //static const std::regex pattern(R"(.*-T\d+\.pack)");
    //return !std::regex_match(filename, pattern);
}

// 生成新文件名（修改后）
std::string GenerateNewFilename(const std::string& rootPath, const std::string& filePath, int fileCount) {
    // 获取文件所在目录路径
    size_t lastSlash = filePath.find_last_of("\\/");
    std::string dirPath = (lastSlash != std::string::npos) ?
        filePath.substr(0, lastSlash) : filePath;

    // 计算目录的相对路径
    std::string relativePath = GetRelativePath(dirPath, rootPath);

    // 清理相对路径（移除开头的斜杠）
    if (!relativePath.empty() && (relativePath[0] == '\\' || relativePath[0] == '/')) {
        relativePath = relativePath.substr(1);
    }

    // 替换路径分隔符为短横线
    std::string pathPart = ReplaceAll(relativePath, "\\", "-");
    if (!pathPart.empty()) pathPart += "-";

    // 组合新文件名
    return pathPart + "T" + std::to_string(fileCount) + ".pack";
}

// 递归遍历目录并收集文件信息
void CollectFiles(const std::string& directory, std::unordered_map<std::string, int>& dirCounts,
    std::vector<std::pair<std::string, std::string>>& filesToRename) {
    std::string searchPath = directory + "\\*";
    WIN32_FIND_DATAA findData;
    HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData);

    if (hFind != INVALID_HANDLE_VALUE) {
        do {
            if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0)
                continue;

            std::string fullPath = directory + "\\" + findData.cFileName;

            if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                // 递归处理子目录
                CollectFiles(fullPath, dirCounts, filesToRename);
            }
            else {
                // 普通文件
                if (PathMatchSpecA(findData.cFileName, "*.pack")) {
                    std::string dirPath = directory;
                    dirCounts[dirPath]++;

                    // 检查是否需要重命名
                    if (NeedsRename(findData.cFileName)) {
                        filesToRename.push_back({ fullPath, dirPath });
                    }
                }
            }
        } while (FindNextFileA(hFind, &findData) != 0);

        FindClose(hFind);
    }
}

int main(int argc, char* argv[]) {
    // 检查命令行参数
   /* if (argc != 2) {
        std::cerr << "用法: " << argv[0] << " <目录路径>" << std::endl;
        return 1;
    }*/

    // 获取指定目录C:\数据库
    //std::string rootPath = argv[1];
    std::string rootPath = "C:\\数据库";

    // 确保路径以反斜杠结尾
    if (rootPath.back() != '\\' && rootPath.back() != '/') {
        rootPath += '\\';
    }

    // 检查目录是否存在
    DWORD fileAttributes = GetFileAttributesA(rootPath.c_str());
    if (fileAttributes == INVALID_FILE_ATTRIBUTES || !(fileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
        std::cerr << "错误: 指定的路径不存在或不是目录 - " << rootPath << std::endl;
        return 1;
    }

    std::cout << "正在处理目录: " << rootPath << std::endl;

    // 用于存储每个目录中的文件计数
    std::unordered_map<std::string, int> directoryCounts;
    // 存储需要重命名的文件
    std::vector<std::pair<std::string, std::string>> filesToRename;

    try {
        // 收集所有需要重命名的文件
        CollectFiles(rootPath, directoryCounts, filesToRename);

        // 处理文件并重命名
        for (auto& fileInfo : filesToRename) {
            const std::string& filePath = fileInfo.first;
            const std::string& dirPath = fileInfo.second;

            // 获取文件名部分
            size_t lastSlash = filePath.find_last_of("\\/");
            std::string fileName = (lastSlash != std::string::npos) ?
                filePath.substr(lastSlash + 1) : filePath;

            // 获取当前目录的文件计数
            int fileCount = directoryCounts[dirPath];

            // 生成新文件名
            std::string newFilename = GenerateNewFilename(rootPath, filePath, fileCount);
            std::string newPath = dirPath + "\\" + newFilename;

            // 执行重命名
            std::cout << "重命名: " << filePath << " -> " << newPath << std::endl;
            if (!MoveFileA(filePath.c_str(), newPath.c_str())) {
                std::cerr << "  失败: " << GetLastError() << std::endl;
            }

            // 减少计数
            directoryCounts[dirPath]--;
        }

        std::cout << "文件重命名完成！" << std::endl;
    }
    catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}